#include "keymngr.h"
#include "dh.h"
#include "incognito.h"

void keymngr::get_key(incognito_impl *ic,chord_node &n,cbgetkey cb)
{
	bigint key;
	getkeyres res=INCOGNITO_KEY_FAILED;

	warnx << "keymngr::get_key(" << n.x << ");\n";

	keymap::const_iterator i=_keys.find(n.x);

	if (i==_keys.end())
	{
		warnx << "keymngr::get_key(" << n.x << "): key not found\n";
		_keys[n.x]=dh();

		dh &k=_keys[n.x];
		warnx << "keymngr::get_key(" << n.x << "): calling dh_exchange\n";
		ic->dh_exchange(n,k.get_p(),k.get_g(),k.get_pubkey(),wrap(mkref(this),&keymngr::get_key_dh_exchange_cb,n,cb));

	}
	else
	{
		warnx << "keymngr::get_key(" << n.x << "): key found\n";
		dh k=i->second;

		if (k.ok()) {
			//warnx << "keymngr::get_key(" << n.x << "): key found and ok\n";
			key=k.get_secret();
			res=INCOGNITO_KEY_OK;
		} else {
			warnx << "keymngr::get_key(" << n.x << ") - key not found FIXME: " << __FILE__ << ":" << __LINE__ << "\n";
		}
		cb(key,res);
	}
}
// Get encryption key for node n and call cb (don't establish new if key doesn't exists yet)
void keymngr::get_key(incognito_impl *ic, chordID id, cbgetkey cb)
{
	bigint key;
	getkeyres res=INCOGNITO_KEY_FAILED;

	keymap::const_iterator i=_keys.find(id);
	if (i!=_keys.end()) {
		dh k=i->second;

		if (k.ok()) {
			//warnx << "keymngr::get_key(" << n.x << "): key found and ok\n";
			key=k.get_secret();
			res=INCOGNITO_KEY_OK;
		} else {
			warnx << "keymngr::get_key_no_new(" << id << ") - key not ok FIXME: " << __FILE__ << ":" << __LINE__ << "\n";
		}
	} else {
		warnx << "keymngr::get_key_no_new(" << id << ") - key not found FIXME: " << __FILE__ << ":" << __LINE__ << "\n";
	}
	cb(key,res);
}
void keymngr::get_key_dh_exchange_cb(chord_node n, cbgetkey cb,bigint remote_pubkey)
{
	//FIXME: what when RPC will crush?
	//
	warnx << "keymngr::get_key_dh_exchange_cb(" << n.x << ")\n";
	warnx << "keymngr::get_key_dh_exchange_cb(): remote_pubkey=" << remote_pubkey << "\n";
	_keys[n.x].set_rpubkey(remote_pubkey);
	if (_keys[n.x].ok())
		cb(_keys[n.x].get_secret(),INCOGNITO_KEY_OK);
	else {
		warnx << "keymngr::get_key_dh_exchange_cb(" << n.x << ") - key not ok FIXME: " << __FILE__ << ":" << __LINE__ << "\n";
		cb(_keys[n.x].get_secret(),INCOGNITO_KEY_FAILED);
	}
}

bigint keymngr::on_key_exchange(chordID node,bigint p, bigint g, bigint remote_pubkey)
{
	//warnx << "keymngr::on_key_exchange()\n";
	keymap::const_iterator i=_keys.find(node);
	if (i==_keys.end()) {
		//warnx << "keymngr::on_key_exchange() - new key\n";
		_keys[node]=dh(p,g,remote_pubkey);
	} else {
		// FIXME: co zrobić jak już klucz istnieje?
		warnx << "keymngr::on_key_exchange() - key exists FIXME: " << __FILE__ << ":" << __LINE__ << "\n";
		if ((i->second.get_p()==p) && (i->second.get_g()==g)) {
			warnx << "keymngr::on_key_exchange() - key exists - group parameters match FIXME\n";
		}
	}
	return _keys[node].get_pubkey();
}
void keymngr::print_stats()
{
	warnx << "keymngr::print_stats() - start -------------------\n";
	for (keymap::const_iterator i=_keys.begin();i!=_keys.end();++i) {
		warnx << "[" << i->first << "]=";
		if (i->second.ok())
			warnx << i->second.get_secret() << "\n";
		else
		warnx << "not completed\n";
		warnx << "\tLOCAL PUBKEY =" << i->second.get_pubkey() <<"\n";
		warnx << "\tREMOTE PUBKEY=" << i->second.get_rpubkey() << "\n";
	}
	warnx << "keymngr::print_stats() - stop  -------------------\n";
}
